module Mtop();
   
   booth2_16x16 u_1( 
   					 .i_a(16'habcd),
   					 .i_b(16'h5678),
   					 .i_sign(1'b1) );
   
   // reg [7:0] a, b;
   // reg 		 sign;
   
   // booth2 u_1( .i_a(a),
   // 	       .i_b(b),
   // 	       .i_sign(sign) );

   // initial begin
   // 	  a = 8'hab;
   // 	  b = 8'h56;

   // 	  #10 a = 8'hcd;
   // 	  b = 8'h78;
	  
   // 	  #10 a = 8'hcd;
   // 	  b = 8'h77;
   // end

   
endmodule // Mtop


  
module booth2_16x16(
					input [15:0] i_a,
					input [15:0] i_b, // multiplier
					input 		 i_sign
					);

   wire [15+1:0] 				 a = {i_sign & i_a[15], i_a};
   wire [15+3:0] 				 b_ext = {{2{i_sign & i_b[15]}}, i_b, 1'b0}; // extend 2 sign bit in the MSB and one 0 in LSB, total 19 bits
   // wire [15+1:0] 				 b_ext = {i_b, 1'b0}; // total 16/2=8 PPs
								
   
   
								 
								 
   
   reg signed [7:0] 			 booth_array[4:0];	// 0, +-1, +-2
   reg signed [15+1:0] 			 pp[7:0];	// the width should be 17(one bit more than original input)
   
   // reg signed [18:0] 			 result;
   
   // reg signed [18:0] 			 pp_sc[4:0]; // pp with sign compensation
   // reg signed [18:0] 			 sc[4:0];	  // sign compensation
   

   // reg signed [18:0] 			 pp_sc2[4:0]; // pp with sign compensation
   // reg signed [18:0] 			 sc2[4:0];	  // sign compensation
   
   // reg signed [18:0] 			 tmp;
   
   // wire [18:0] 					 a_pp_1 = {{10{1'b1}}, ~a[8], a[7:0]};
   // wire [18:0] 					 a_pp = a_pp_1 + 19'h100;
   
   
   always_comb
	 begin
		// $display("a = %x, b = %x", a, b);
		
		// booth recoding 
		// for(int i=0;i<=16;i+=2)
		for(int i=0;i<=16;i+=2)	// total 9 PPs			// indeed, if the input is signed num, only need 8 PPs
		  begin
			 booth_array[i/2] = b_ext[i] + b_ext[i+1] - 2*b_ext[i+2];
			 $display("booth_arry[%d] = %d", i/2, booth_array[i/2]);
		  end
		
		//partitical product
		for(int i=0;i<=8;i+=1)
		  begin
			 pp[i] = ($signed(a) * booth_array[i]) << (2*i);
			 $display("pp[%d] = 0x%x * %d = %x", i, a, booth_array[i], pp[i]);
		  end
	 end // always_comb
   
		
	 // 	// the result (addition)
	 // 	result = 19'd0;
	 // 	for(int i=0;i<=4;i++)
	 // 	  result += pp[i];
		
	 // 	$display("result : %x", result);
	 // 	$display("result : %d", result);


	 // 	// sign compensation
	 // 	for(int i=0;i<=4;i++)
	 // 	  begin
	 // 		 $display("sign of pp[%d] = %d", i, pp[i][8+i*2]);
	 // 		 // pp_sc[i] = { {(19-(8+i*2+1)){1'b1}}, ~pp[i][8+i*2], pp[i][8+i*2-1:0] };
	 // 	  end
	 // 	pp_sc[0] = { {10{1'b1}}, ~pp[0][8], pp[0][7:0] };
	 // 	pp_sc[1] = { {8{1'b1}}, ~pp[1][10], pp[1][9:0] };
	 // 	pp_sc[2] = { {6{1'b1}}, ~pp[2][12], pp[2][11:0] };
	 // 	pp_sc[3] = { {4{1'b1}}, ~pp[3][14], pp[3][13:0] };
	 // 	pp_sc[4] = { {2{1'b1}}, ~pp[4][16], pp[4][15:0] };

	 // 	sc[0] = { 10'b0, 1'b1, 8'b0 };
	 // 	sc[1] = { 8'b0, 1'b1, 10'b0 };
	 // 	sc[2] = { 6'b0, 1'b1, 12'b0 };
	 // 	sc[3] = { 4'b0, 1'b1, 14'b0 };
	 // 	sc[4] = { 2'b0, 1'b1, 16'b0 };


	 // 	// sc2 : the second sign compensation method
	 // 	pp_sc2[0] = { {10{1'b0}}, ~pp[0][8], pp[0][7:0] };
	 // 	pp_sc2[1] = { {8{1'b0}}, ~pp[1][10], pp[1][9:0] };
	 // 	pp_sc2[2] = { {6{1'b0}}, ~pp[2][12], pp[2][11:0] };
	 // 	pp_sc2[3] = { {4{1'b0}}, ~pp[3][14], pp[3][13:0] };
	 // 	pp_sc2[4] = { {2{1'b0}}, ~pp[4][16], pp[4][15:0] };

	 // 	sc2[0] = { {10{1'b1}}, 1'b1, 8'b0 };
	 // 	sc2[1] = { {8{1'b1}}, 1'b1, 10'b0 };
	 // 	sc2[2] = { {6{1'b1}}, 1'b1, 12'b0 };
	 // 	sc2[3] = { {4{1'b1}}, 1'b1, 14'b0 };
	 // 	sc2[4] = { {2{1'b1}}, 1'b1, 16'b0 };

		
	 // 	result = 19'd0;
	 // 	for(int i=0;i<=4;i++)
	 // 	  begin
	 // 		 $display("pp after sign compensation : pp_sc[%d] = %x, pp_sc (%x) ", i, pp_sc[i], pp_sc[i]+sc[i]);
	 // 		 result += pp_sc[i] + sc[i];
	 // 	  end

	 // 	$display("result after sign compensation : %d", result);
		
	 // 	tmp = 19'd0;
	 // 	for(int i=0;i<=4;i++)
	 // 	  tmp += sc[i];
		
	 // 	$display("the sum of sign compensation is : %x", tmp);


	 // 	// first calc the sum of pp_sc
	 // 	result = 0;
	 // 	for(int i=0;i<=4;i++)
	 // 	  result += pp_sc[i];
	 // 	$display("the sum of pp without sign compensation is : %x", result);
	 // 	tmp = 0;
	 // 	for(int i=0;i<=4;i++)
	 // 	  tmp += sc[i];
	 // 	$display("the sum of sign compensation is : %x", tmp);
		
	 // 	result += tmp;
	 // 	$display("the final sum of pp is : %x (%d)", result, result);
		


	 // 	//the second sign compensation method
	 // 	result = 19'd0;
	 // 	for(int i=0;i<=4;i++)
	 // 	  begin
	 // 		 $display("pp after sign compensation method 2 : pp_sc2[%d] = %x, pp_sc2 (%x) ", i, pp_sc2[i], pp_sc2[i]+sc2[i]);
	 // 		 result += pp_sc2[i] + sc2[i];
	 // 	  end
	 // 	$display("the final sum of pp is : %x (%d)", result, result);
		
	 // 	tmp = 19'd0;
	 // 	for(int i=0;i<=4;i++)
	 // 	  tmp += sc2[i];
	 // 	$display("the sum of sign compensation method 2 is : %x", tmp);

	 // 	// $display("pp[0] with sign compensation : %x", $signed({ {9{1'b1}}, ~pp[0][9], pp[0][8:0]}) + $signed({{9{1'b0}}, 1'b1, {9{1'b0}} }));
	 // 	// 				   
	 // 	// wire [18:0] a_pp = {{10{1'b1}}, ~a[8], a[7:0]};
	 // 	// $display("a_pp(after extened): %x", a_pp_1);
	 // 	// $display("a_pp = %x", a_pp);
		
		
		
	 // end


   
   
   
  // initial begin
  // 	 #20
  //      for(int i=0;i<=4;i++)
  //  		 $display("booth_arry[%d] = %d", i, booth_array[i]);
  // end

endmodule

      
